#!/usr/local/bin/python3
# -*- coding: utf-8 -*-

"""
@File    :最小外接矩形.py
@Author  :keyin
@Time    :2021-02-01 21:30
"""
# !/usr/local/bin/python3
# -*- coding: utf-8 -*-

"""
@File    :demo.py
@Author  :keyin
@Time    :2021-01-31 11:16
"""

import cv2
import os
from PyQt5.Qt import *
import numpy as np
import math
from PIL import Image
import matplotlib.pyplot as plt
from math import *


def mySize(img, size):
    """

    :param imgshape: img.shape得到图片的宽和高
    :param size: 在屏幕上最长边的尺寸
    :return:
    """

    y = img.shape[0]
    x = img.shape[1]
    multiples = 1
    if y > size or x > size:
        multiples_y = y // size
        multiples_x = x // size

        if multiples_x > multiples_y:
            multiples = multiples_x + 1
        else:
            multiples = multiples_y + 1

    y = y // multiples
    x = x // multiples

    img_show = cv2.resize(img, (x, y))
    cv2.imshow('image', img_show)

    return x, y


def minAr(img):
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 转化为灰度图
    blur = cv2.GaussianBlur(gray, (3, 3), 0)  # 用高斯滤波处理原图像降噪
    blur = cv2.GaussianBlur(blur, (3, 3), 0)  # 用高斯滤波处理原图像降噪
    canny = cv2.Canny(blur, 20, 80)  # 20是最小阈值,50是最大阈值 边缘检测
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
    dilation = cv2.dilate(canny, kernel, iterations=1)  # 膨胀一下，来连接边缘
    dilation = cv2.dilate(dilation, kernel, iterations=1)  # 膨胀一下，来连接边缘
    # dilation = cv2.GaussianBlur(dilation, (3, 3), 0)  # 用高斯滤波处理原图像降噪
    im2, contours, hierarchy = cv2.findContours(dilation, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_TC89_KCOS)  # 找边框

    c_list = []
    max_s = 0
    cc = 0

    for c in contours:
        x, y, w, h = cv2.boundingRect(c)
        c_list.append((w, h))

    for i in range(len(c_list)):
        s = c_list[i][0] + c_list[i][1]
        if s > max_s:
            max_s = s
            cc = i

    x, y, w, h = cv2.boundingRect(contours[cc])
    minBox = cv2.rectangle(im2, (x, y), (x + w, y + h), (255, 255, 255), 5)

    print("-----", x, y, w, h)
    # rect = cv2.minAreaRect(c)
    # box = cv2.boxPoints(rect)
    # box = np.int0(box)
    # minBox = cv2.drawContours(img, [box], 0, (0, 0, 255), 3)

    # c = x
    # d = x+w
    # a = y
    # b = y+h
    #
    # minBox = img[a:b, c:d]

    return minBox


def findBorder(img):
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 转化为灰度图
    blur = cv2.GaussianBlur(gray, (3, 3), 0)  # 用高斯滤波处理原图像降噪
    blur = cv2.GaussianBlur(blur, (3, 3), 0)  # 用高斯滤波处理原图像降噪
    canny = cv2.Canny(blur, 20, 80)  # 20是最小阈值,50是最大阈值 边缘检测
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
    dilation = cv2.dilate(canny, kernel, iterations=1)  # 膨胀一下，来连接边缘
    dilation = cv2.dilate(dilation, kernel, iterations=1)  # 膨胀一下，来连接边缘
    dilation = cv2.GaussianBlur(dilation, (3, 3), 0)  # 用高斯滤波处理原图像降噪
    im2, contours, hierarchy = cv2.findContours(dilation, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_TC89_KCOS)  # 找边框
    return contours
    # return im2


def max_s(contours):
    max_s = 0
    box_max = object()
    s_list = []
    for c in range(len(contours)):
        rect = cv2.minAreaRect(contours[c])
        box = cv2.boxPoints(rect)
        box = np.int0(box)
        x = box[0][0]
        y = box[0][1]
        x1 = box[1][0]
        y1 = box[1][1]
        x = (x - x1) ** 2
        y = (y - y1) ** 2
        s = math.sqrt(x + y)

        if s > max_s:
            max_s = s
            box_max = box

    return box_max


def max_s2(contours):
    s_list = []

    for c in range(len(contours)):
        rect = cv2.minAreaRect(contours[c])
        box = cv2.boxPoints(rect)
        box = np.int0(box)
        x = box[0][0]
        y = box[0][1]
        x1 = box[1][0]
        y1 = box[1][1]
        x = (x - x1) ** 2
        y = (y - y1) ** 2
        s = math.sqrt(x + y)
        s_list.append(s)

    new_list = sorted(s_list)
    # print('-------', new_list)

    return new_list


def lineAngle(box_max):
    new_box = caiqie(box_max)
    x1 = new_box[0][0]
    y1 = new_box[0][1]
    x2 = new_box[1][0]
    y2 = new_box[1][1]

    k = (y2 - y1) / (x2 - x1)
    # print(k)
    a = math.atan(k)
    b = math.degrees(a)

    degree = b + 90

    return degree


def min(img):
    contours = findBorder(img)
    box_max = max_s(contours)

    for poit in box_max:
        x = poit[0]
        y = poit[1]
        cv2.circle(img, (x, y), 10, (255, 0, 0), -1)

    degree = lineAngle(box_max)
    height, width = img.shape[:2]

    minBox = cv2.drawContours(img, [box_max], 0, (0, 0, 255), 3)

    # 旋转后的尺寸
    heightNew = int(width * fabs(sin(radians(degree))) + height * fabs(cos(radians(degree))))
    widthNew = int(height * fabs(sin(radians(degree))) + width * fabs(cos(radians(degree))))

    matRotation = cv2.getRotationMatrix2D((width / 2, height / 2), degree, 1)

    matRotation[0, 2] += (widthNew - width) / 2  # 重点在这步，目前不懂为什么加这步
    matRotation[1, 2] += (heightNew - height) / 2  # 重点在这步

    imgRotation = cv2.warpAffine(minBox, matRotation, (widthNew, heightNew), borderValue=(0, 0, 0))

    contours = findBorder(imgRotation)
    box_max = max_s(contours)
    # max_s2(contours)

    # hull = cv2.convexHull(box_max)
    # print(hull)
    # length = len(hull)
    # for i in range(len(hull)):
    #     cv2.line(img,tuple(hull[i][0]),tuple(hull[(i+1)%length][0]),(0,255,0),2)

    # minBox = cv2.drawContours(minBox, [box_max], 0, (0, 255, 0), 3)
    # print(minBox.shape)

    return minBox


def caiqie(box):
    contours = findBorder(img)
    box_max = max_s(contours)

    for poit in box_max:
        x = poit[0]
        y = poit[1]
        cv2.circle(img, (x, y), 10, (255, 0, 0), -1)


def ROI_byMouse(img):
    contours = findBorder(img)
    box_max = max_s(contours)
    w = 856
    h = 540
    # arr = np.array[(0, 0), (w, 0), (0, h), (w, h)]
    arr = [[0, 0], [w, 0], [0, h], [w, h]]
    # line_intersect = [[40, 200], [2000, 300], [1800,2300], [100, 2400]]
    # s1 = (290, 620)
    # s2 = (2865, 590)
    # s3 = (2900, 2250)
    # s4 = (200, 2250)
    # line_intersect = np.array([s1, s2, s3, s4], dtype=np.float32)
    line_intersect = np.array(box_max, dtype=np.float32)
    target_clockwise_point = target_vertax_poin(arr)
    # draw_point(img,line_intersect)
    matrix = cv2.getPerspectiveTransform(line_intersect, target_clockwise_point)
    endimg = cv2.warpPerspective(img, matrix, (target_clockwise_point[2][0], target_clockwise_point[2][1]))

    # draw_point(img, [s1, s2, s3, s4])

    return endimg

def order_point(points):
    """
    对交点坐标进行排序
    :param points:
    :return:
    """
    points_array = np.array(points)
    x_sort = np.argsort(points_array[:, 0])
    y_sort = np.argsort(points_array[:, 1])
    left_point = points_array[x_sort[0]]
    right_point = points_array[x_sort[-1]]
    top_point = points_array[y_sort[0]]
    bottom_point = points_array[y_sort[-1]]
    return np.array([left_point, top_point, right_point, bottom_point])

def target_vertax_poin(clockwise_point):
    w1 = np.linalg.norm(clockwise_point[0]-clockwise_point[1])
    w2 = np.linalg.norm(clockwise_point[2]-clockwise_point[3])
    w = w1 if w1 > w2 else w2
    h1 = np.linalg.norm(clockwise_point[1]-clockwise_point[2])
    h2 = np.linalg.norm(clockwise_point[3]-clockwise_point[0])
    h = h1 if h1 > h2 else h2
    w = int(round(w))
    h = int(round(h))
    if w>h:
        a = w
        w = h
        h = a
    top_left = [0, 0]
    top_right = [w, 0]
    bottom_right = [w, h]
    bottom_left = [0, h]
    return np.array([top_left, top_right, bottom_right, bottom_left], dtype=np.float32)

def draw_line(img,lines):
    for line_points in lines:
        cv2.line(img,(line_points[0][0], line_points[0][1], line_points[0][2], line_points[0][3]), (0,255,0),2,8,0)
    cv2.imshow('lineimg', img)
    cv2.waitKey(0)

def draw_point(img,points):
    for position in points:
        cv2.circle(img,position,50,(0,255,0),-1)

    size = mySize(img, 600)
    img2 = cv2.resize(img,size)
    cv2.imshow("draw_point",img2)
    cv2.waitKey(0)

# 顺时针旋转90度
def RotateClockWise90(img):
    trans_img = cv2.transpose(img)
    new_img = cv2.flip(trans_img, 1)
    return new_img


def toushi(img):
    contours = findBorder(img)
    box_max = max_s(contours)
    # print(box_max)
    w = 856
    h = 540
    arr =np.array([[0,0],[w,0],[0,h],[w,h]],dtype=np.float32)
    line_intersect = np.array(box_max, dtype=np.float32)
    target_clockwise_point = target_vertax_poin(arr)

    matrix = cv2.getPerspectiveTransform(line_intersect, target_clockwise_point)
    endimg = cv2.warpPerspective(img, matrix,(target_clockwise_point[2][0], target_clockwise_point[2][1]))
    # endimg = RotateClockWise90(endimg)
    # endimg = RotateClockWise90(endimg)
    # endimg = RotateClockWise90(endimg)

    # endimg = findBorder(endimg)

    return endimg


if __name__ == '__main__':
    img_path = '444.jpg'
    img = cv2.imread(img_path)
    # minbox = min(img)
    # minbox = findBorder(img)
    minbox = toushi(img)
    # minbox = toushi(minbox)

    size = mySize(minbox, 1000)
    minbox = cv2.resize(minbox,size)
    cv2.imshow('kj',minbox)
    # cv2.imwrite("444.jpg",minbox)

    # toushi(img)

    cv2.waitKey(0)
    cv2.destroyAllWindows()
